home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 3 / Cream of the Crop 3.iso / comm / wnos5src.zip / SOCKET.C < prev    next >
Text File  |  1993-08-09  |  45KB  |  1,960 lines

  1. #include <stdio.h>
  2. #ifdef    __STDC__
  3. #include <stdarg.h>
  4. #endif
  5. #include "global.h"
  6. #include "config.h"
  7. #include "mbuf.h"
  8. #include "netuser.h"
  9. #include "timer.h"
  10. #include "iface.h"
  11. #include "ip.h"
  12. #include "tcp.h"
  13. #ifdef UDP
  14. #include "udp.h"
  15. #endif
  16. #include "ax25.h"
  17. #include "netrom.h"
  18. #include "nr4.h"
  19. #include "proc.h"
  20. #ifdef LZW
  21. #include "lzw.h"
  22. #endif
  23. #include "usock.h"
  24. #include "socket.h"
  25.  
  26. static void near autobind __ARGS((int s,int af));
  27. static int near checkaddr __ARGS((int type,char *name,int namelen));
  28. static void rip_recv __ARGS((struct raw_ip *rp));
  29. void s_trcall __ARGS((struct tcb *tcb,int cnt));
  30. void s_tscall __ARGS((struct tcb *tcb,int old,int new));
  31. void s_ttcall __ARGS((struct tcb *tcb,int cnt));
  32. #ifdef UDP
  33. void s_urcall __ARGS((struct iface *iface,struct udp_cb *udp,int cnt));
  34. #endif
  35. static void trdiscard __ARGS((struct tcb *tcb,int cnt));
  36. #ifdef    NETROM
  37. void s_nrcall __ARGS((struct nr4cb *cb,int cnt));
  38. void s_nscall __ARGS((struct nr4cb *cb,int old,int new));
  39. void s_ntcall __ARGS((struct nr4cb *cb,int cnt));
  40. #endif
  41.  
  42. static int16 Lport = 1024;
  43.  
  44. char Badsocket[] = "Bad socket";
  45. char Nosocket[] = "Can't create socket\n";
  46.  
  47. static struct usock *Usock = NULLUSOCK;        /* Socket entry array */
  48. int Nusock = DEFNSOCK;                        /* Number of socket entries */
  49.  
  50. /* The following two variables are needed because there can be only one
  51.  * socket listening on each of the AX.25 modes (I and UI)
  52.  */
  53.  /* definition !! */
  54. /*
  55. int Axi_sock = -1;        /* Socket number listening for AX25 connections */
  56.                         /* defined in server.c */
  57. #ifdef AX25
  58. static int Axui_sock = -1;    /* Socket number listening for AX25 UI frames */
  59. #endif /* AX25 */
  60.  
  61. /* Initialize user socket array */
  62. void
  63. sockinit()
  64. {
  65.     Usock = (struct usock *)mxalloc(Nusock * sizeof(struct usock));
  66. }
  67.  
  68. /* Create a user socket, return socket index
  69.  * The mapping to actual protocols is as follows:
  70.  *
  71.  * ADDRESS FAMILY    Stream        Datagram    Raw        Seq. Packet
  72.  *
  73.  * AF_INET            TCP            UDP            IP
  74.  * AF_AX25            I-frames    UI-frames
  75.  * AF_NETROM        NET/ROM L3  NET/ROM L4
  76.  * AF_LOCAL            stream loopback    packet loopback
  77.  */
  78. int
  79. socket(
  80. int af,                /* Address family */
  81. int type,            /* Stream or datagram */
  82. int protocol)        /* Used for raw IP sockets */
  83. {
  84.     struct usock *up;
  85.     int s;
  86.  
  87.     errno = 0;
  88.  
  89.     for(up = Usock; up < &Usock[Nusock]; up++)
  90.         if(up->type == NOTUSED)
  91.             break;
  92.  
  93.     if(up == &Usock[Nusock]) {
  94.         /* None left */
  95.         errno = EMFILE;
  96.         return EOF;
  97.     }
  98.  
  99.     s = (int)(up - Usock) + SOCKBASE;
  100.  
  101.     up->refcnt = 1;
  102.     up->noblock = 0;
  103.     up->rdysock = -1;
  104.     up->cb.p = NULLCHAR;
  105.     up->name = up->peername = NULLCHAR;
  106.     up->namelen = up->peernamelen = 0;
  107.     up->owner = Curproc;
  108.     up->obuf = NULLBUF;
  109.  
  110.     memset(up->errcodes,0,sizeof(up->errcodes));
  111.     memset(up->eol,0,sizeof(up->eol));
  112.  
  113.     up->flush = '\n';    /* default is line buffered */
  114.  
  115.     switch(af) {
  116.     case AF_LOCAL:
  117.         up->cb.local = (struct loc *)mxallocw(sizeof(struct loc));
  118.         up->cb.local->peer = up;
  119.         switch(type){
  120.         case SOCK_STREAM:
  121.             up->type = TYPE_LOCAL_STREAM;
  122.             up->cb.local->hiwat = LOCSFLOW;
  123.             break;
  124.         case SOCK_DGRAM:
  125.             up->type = TYPE_LOCAL_DGRAM;
  126.             up->cb.local->hiwat = LOCDFLOW;
  127.             break;
  128.         default:
  129.             xfree(up->cb.local);
  130.             errno = ESOCKTNOSUPPORT;
  131.             break;
  132.         }
  133.         break;
  134. #ifdef    AX25
  135.     case AF_AX25:
  136.         switch(type){
  137.         case SOCK_STREAM:
  138.             up->type = TYPE_AX25I;
  139.             break;
  140.         case SOCK_DGRAM:
  141.             up->type = TYPE_AX25UI;
  142.             break;
  143.         default:
  144.             errno = ESOCKTNOSUPPORT;
  145.             break;
  146.         }
  147.         strcpy(up->eol,AX_EOL);
  148.         break;
  149. #endif
  150. #ifdef NETROM
  151.     case AF_NETROM:
  152.         switch(type){
  153.         case SOCK_RAW:
  154.             up->type = TYPE_NETROML3;
  155.             up->cb.rnr = raw_nr((char)protocol);
  156.             break;
  157.         case SOCK_SEQPACKET:
  158.             up->type = TYPE_NETROML4;
  159.             break;
  160.         default:
  161.             errno = ESOCKTNOSUPPORT;
  162.             break;
  163.         }
  164.         strcpy(up->eol,AX_EOL);
  165.         break;
  166. #endif
  167.     case AF_INET:
  168.         switch(type){
  169.         case SOCK_STREAM:
  170.             up->type = TYPE_TCP;
  171.             strcpy(up->eol,INET_EOL);
  172.             break;
  173.         case SOCK_DGRAM:
  174.             up->type = TYPE_UDP;
  175.             break;
  176.         case SOCK_RAW:
  177.             up->type = TYPE_RAW;
  178.             up->cb.rip = raw_ip(protocol,rip_recv);
  179.             up->cb.rip->user = s;
  180.             break;
  181.         default:
  182.             errno = ESOCKTNOSUPPORT;
  183.             break;
  184.         }
  185.         break;
  186.     default:
  187.         errno = EAFNOSUPPORT;
  188.         break;
  189.     }
  190.     if(errno)
  191.         return -1;
  192.  
  193.     return s;
  194. }
  195.  
  196. /* Attach a local address/port to a socket. If not issued before a connect
  197.  * or listen, will be issued automatically
  198.  */
  199. int
  200. bind(
  201. int s,                /* Socket index */
  202. char *name,            /* Local name */
  203. int namelen)        /* Length of name */
  204. {
  205.     struct usock *up;
  206.     union sp local;
  207.     struct socket lsock;
  208.  
  209.     if((up = itop(s)) == NULLUSOCK){
  210.         return EOF;
  211.     }
  212.     if(up->type == TYPE_LOCAL_STREAM
  213.       || up->type == TYPE_LOCAL_DGRAM
  214.       /* Bind has already been issued */
  215.       || up->name != NULLCHAR) {
  216.         errno = EINVAL;
  217.         return EOF;
  218.     }
  219.     if(name == NULLCHAR){
  220.         errno = EFAULT;
  221.         return EOF;
  222.     }
  223.     if(checkaddr(up->type,name,namelen) == -1){
  224.         /* Incorrect length or family for chosen protocol */
  225.         errno = EAFNOSUPP;
  226.         return EOF;
  227.     }
  228.     /* Stash name in an allocated block */
  229.     up->name = mxallocw(namelen);
  230.     memcpy(up->name,name,namelen);
  231.     up->namelen = namelen;
  232.     /* Create control block for datagram sockets */
  233.     switch(up->type){
  234. #ifdef UDP
  235.     case TYPE_UDP:
  236.         local.in = (struct sockaddr_in *)up->name;
  237.         lsock.address = local.in->sin_addr.s_addr;
  238.         lsock.port = local.in->sin_port;
  239.         up->cb.udp = open_udp(&lsock,s_urcall);
  240.         up->cb.udp->user = s;
  241.         break;
  242. #endif
  243. #ifdef    AX25
  244.     case TYPE_AX25UI:
  245.         if(Axui_sock != -1){
  246.             errno = EADDRINUSE;
  247.             return EOF;
  248.         }
  249.         Axui_sock = s;
  250.         break;
  251. #endif
  252.     }
  253.     return 0;
  254. }
  255. /* Post a listen on a socket */
  256. int
  257. listen(
  258. int s,                /* Socket index */
  259. int backlog)        /* 0 for a single connection, 1 for multiple connections */
  260. {
  261.     struct usock *up;
  262.     union sp local;
  263.     struct socket lsock;
  264.  
  265.     if((up = itop(s)) == NULLUSOCK){
  266.         return EOF;
  267.     }
  268.     if(up->type == TYPE_LOCAL_STREAM || up->type == TYPE_LOCAL_DGRAM){
  269.         errno = EINVAL;
  270.         return EOF;
  271.     }
  272.     if(up->cb.p != NULLCHAR){
  273.         errno = EISCONN;
  274.         return EOF;
  275.     }
  276.     switch(up->type){
  277.     case TYPE_TCP:
  278.         if(up->name == NULLCHAR)
  279.             autobind(s,AF_INET);
  280.  
  281.         local.in = (struct sockaddr_in *)up->name;
  282.         lsock.address = local.in->sin_addr.s_addr;
  283.         lsock.port = local.in->sin_port;
  284.         up->cb.tcb = open_tcp(
  285.             &lsock,
  286.             NULLSOCK,
  287.             backlog ? TCP_SERVER : TCP_PASSIVE,
  288.             0,
  289.             s_trcall,
  290.             s_ttcall,
  291.             s_tscall,
  292.             0,
  293.             s);
  294.         break;
  295. #ifdef AX25
  296.     case TYPE_AX25I:
  297.         if(up->name == NULLCHAR)
  298.             autobind(s,AF_AX25);
  299.         if(s != Axi_sock){
  300.             errno = EOPNOTSUPP;
  301.             return EOF;
  302.         }
  303.         local.ax = (struct sockaddr_ax *)up->name;
  304.         up->cb.ax25 = open_ax25(
  305.             NULLIF,
  306.             local.ax->ax25_addr,
  307.             NULLCHAR,
  308.             backlog ? AX_SERVER : AX_PASSIVE,
  309.             s_arcall,
  310.             s_atcall,
  311.             s_ascall,
  312.             s);
  313.         break;
  314. #endif
  315. #ifdef NETROM
  316.     case TYPE_NETROML4:
  317.         if(up->name == NULLCHAR)
  318.             autobind(s,AF_NETROM);
  319.         local.nr = (struct sockaddr_nr *)up->name;
  320.         up->cb.nr4 = open_nr4(
  321.             &local.nr->nr_addr,
  322.             NULLNRADDR,
  323.             backlog ? AX_SERVER : AX_PASSIVE,
  324.             s_nrcall,
  325.             s_ntcall,
  326.             s_nscall,
  327.             s);
  328.         break;
  329. #endif
  330.     default:
  331.         /* Listen not supported on datagram sockets */
  332.         errno = EOPNOTSUPP;
  333.         return EOF;
  334.     }
  335.     return 0;
  336. }
  337.  
  338. /* Initiate active open. For datagram sockets, merely bind the remote address. */
  339. int
  340. connect(
  341. int s,                    /* Socket index */
  342. char *peername,            /* Peer name */
  343. int peernamelen)        /* Length of peer name */
  344. {
  345.     struct usock *up;
  346.     union cb cb;
  347.     union sp local,remote;
  348.     struct socket lsock,fsock;
  349. #ifdef    AX25
  350.     struct iface *iface;
  351. #endif
  352.  
  353.     if((up = itop(s)) == NULLUSOCK){
  354.         return EOF;
  355.     }
  356.     if(up->type == TYPE_LOCAL_DGRAM || up->type == TYPE_LOCAL_STREAM){
  357.         errno = EINVAL;
  358.         return EOF;
  359.     }
  360.     if(peername == NULLCHAR){
  361.         /* Connect must specify a remote address */
  362.         errno = EFAULT;
  363.         return EOF;
  364.     }
  365.     if(checkaddr(up->type,peername,peernamelen) == -1){
  366.         errno = EAFNOSUPPORT;
  367.         return EOF;
  368.     }
  369.     /* Raw socket control blocks are created in socket() */
  370.     if(up->type != TYPE_RAW && up->type != TYPE_NETROML3 &&
  371.        up->cb.p != NULLCHAR){
  372.         errno = EISCONN;
  373.         return EOF;
  374.     }
  375.     up->peername = mxallocw(peernamelen);
  376.     memcpy(up->peername,peername,peernamelen);
  377.     up->peernamelen = peernamelen;
  378.  
  379.     /* Set up the local socket structures */
  380.     if(up->name == NULLCHAR){
  381.         switch(up->type){
  382.         case TYPE_TCP:
  383. #ifdef UDP
  384.         case TYPE_UDP:
  385. #endif
  386.         case TYPE_RAW:
  387.             autobind(s,AF_INET);
  388.             break;
  389. #ifdef    AX25
  390.         case TYPE_AX25I:
  391.         case TYPE_AX25UI:
  392.             autobind(s,AF_AX25);
  393.             break;
  394. #endif
  395. #ifdef    NETROM
  396.         case TYPE_NETROML3:
  397.         case TYPE_NETROML4:
  398.             autobind(s,AF_NETROM);
  399.             break;
  400. #endif
  401.         }
  402.     }
  403.     switch(up->type){
  404.     case TYPE_TCP:
  405.         /* Construct the TCP-style ports from the sockaddr structs */
  406.         local.in = (struct sockaddr_in *)up->name;
  407.         remote.in = (struct sockaddr_in *)up->peername;
  408.  
  409.         if(local.in->sin_addr.s_addr == INADDR_ANY)
  410.             /* Choose a local address */
  411.             local.in->sin_addr.s_addr = locaddr(remote.in->sin_addr.s_addr);
  412.  
  413.         lsock.address = local.in->sin_addr.s_addr;
  414.         lsock.port = local.in->sin_port;
  415.         fsock.address = remote.in->sin_addr.s_addr;
  416.         fsock.port = remote.in->sin_port;
  417.  
  418.         /* Open the TCB in active mode */
  419.         up->cb.tcb =
  420.             open_tcp(&lsock,&fsock,TCP_ACTIVE,0,s_trcall,s_ttcall,s_tscall,0,s);
  421.  
  422.         /* Wait for the connection to complete */
  423.         while((cb.tcb = up->cb.tcb) != NULLTCB && cb.tcb->state != TCP_ESTABLISHED){
  424.             if(up->noblock){
  425.                 errno = EWOULDBLOCK;
  426.                 return EOF;
  427.             } else if((errno = (int)pwait(up)) != 0){
  428.                 return EOF;
  429.             }
  430.         }
  431.         if(cb.tcb == NULLTCB){
  432.             /* Probably got refused */
  433.             xfree(up->peername);
  434.             up->peername = NULLCHAR;
  435.             errno = ECONNREFUSED;
  436.             return EOF;
  437.         }
  438.         break;
  439. #ifdef UDP
  440.     case TYPE_UDP:
  441. #endif
  442. #ifdef    AX25
  443.     case TYPE_AX25UI:
  444. #endif
  445. #ifdef    NETROM
  446.     case TYPE_NETROML3:
  447. #endif
  448.     case TYPE_RAW:
  449.         /* Control block already created by bind() */
  450.         break;
  451. #ifdef    AX25
  452.     case TYPE_AX25I:
  453.         local.ax = (struct sockaddr_ax *)up->name;
  454.         remote.ax = (struct sockaddr_ax *)up->peername;
  455.         if((iface = if_lookup(remote.ax->iface)) == NULLIF){
  456.             errno = EINVAL;
  457.             return EOF;
  458.         }
  459.         if(local.ax->ax25_addr[0] == '\0'){
  460.             /* The local address was unspecified; set it from
  461.              * the interface address
  462.              */
  463.             memcpy(local.ax->ax25_addr,iface->hwaddr,AXALEN);
  464.         }
  465.         /* If we already have an AX25 link we can use it */
  466.         if((up->cb.ax25 = find_ax25(local.ax->ax25_addr,remote.ax->ax25_addr)) != NULLAX25
  467.           && up->cb.ax25->state != DISCONNECTED
  468.           && up->cb.ax25->user == -1) {
  469.             up->cb.ax25->user = s;
  470.             up->cb.ax25->r_upcall = s_arcall;
  471.             up->cb.ax25->t_upcall = s_atcall;
  472.             up->cb.ax25->s_upcall = s_ascall;
  473.  
  474.             if(up->cb.ax25->state == CONNECTED)
  475.                 return 0;
  476.         } else {
  477.             up->cb.ax25 = open_ax25(
  478.                 iface,
  479.                 local.ax->ax25_addr,
  480.                 remote.ax->ax25_addr,
  481.                 AX_ACTIVE,
  482.                 s_arcall,
  483.                 s_atcall,
  484.                 s_ascall,
  485.                 s);
  486.         }
  487.  
  488.         /* Wait for the connection to complete */
  489.         while((cb.ax25 = up->cb.ax25) != NULLAX25 && cb.ax25->state != CONNECTED){
  490.             if(up->noblock){
  491.                 errno = EWOULDBLOCK;
  492.                 return EOF;
  493.             } else if((errno = (int)pwait(up)) != 0){
  494.                 return EOF;
  495.             }
  496.         }
  497.         if(cb.ax25 == NULLAX25){
  498.             /* Connection probably already exists */
  499.             xfree(up->peername);
  500.             up->peername = NULLCHAR;
  501.             errno = ECONNREFUSED;
  502.             return EOF;
  503.         }
  504.         break;
  505. #endif
  506. #ifdef    NETROM
  507.     case TYPE_NETROML4:
  508.         local.nr = (struct sockaddr_nr *)up->name;
  509.         remote.nr = (struct sockaddr_nr *)up->peername;
  510.         up->cb.nr4 = open_nr4(
  511.             &local.nr->nr_addr,
  512.             &remote.nr->nr_addr,
  513.             AX_ACTIVE,
  514.             s_nrcall,
  515.             s_ntcall,
  516.             s_nscall,
  517.             s);
  518.  
  519.         /* Wait for the connection to complete */
  520.         while((cb.nr4 = up->cb.nr4) != NULLNR4CB && cb.nr4->state != NR4STCON){
  521.             if(up->noblock){
  522.                 errno = EWOULDBLOCK;
  523.                 return EOF;
  524.             } else if((errno = (int)pwait(up)) != 0){
  525.                 return EOF;
  526.             }
  527.         }
  528.         if(cb.nr4 == NULLNR4CB){
  529.             /* Connection probably already exists */
  530.             xfree(up->peername);
  531.             up->peername = NULLCHAR;
  532.             errno = ECONNREFUSED;
  533.             return EOF;
  534.         }
  535.         break;
  536. #endif
  537.     }
  538.     return 0;
  539. }
  540.  
  541. /* Wait for a connection. Valid only for connection-oriented sockets. */
  542. int
  543. accept(
  544. int s,                    /* Socket index */
  545. char *peername,            /* Peer name */
  546. int *peernamelen)        /* Length of peer name */
  547. {
  548.     int i;
  549.     struct usock *up;
  550.  
  551.     if((up = itop(s)) == NULLUSOCK){
  552.         return EOF;
  553.     }
  554.     if(up->type == TYPE_LOCAL_DGRAM || up->type == TYPE_LOCAL_STREAM){
  555.         errno = EINVAL;
  556.         return EOF;
  557.     }
  558.     if(up->cb.p == NULLCHAR){
  559.         errno = EOPNOTSUPP;
  560.         return EOF;
  561.     }
  562.     /* Accept is valid only for stream sockets */
  563.     switch(up->type){
  564.     case TYPE_TCP:
  565. #ifdef    AX25
  566.     case TYPE_AX25I:
  567. #endif
  568. #ifdef    NETROM
  569.     case TYPE_NETROML4:
  570. #endif
  571.         break;
  572.     default:
  573.         errno = EOPNOTSUPP;
  574.         return EOF;
  575.     }
  576.     /* Wait for the state-change upcall routine to signal us */
  577.     while(up->cb.p != NULLCHAR && up->rdysock == -1){
  578.         if(up->noblock){
  579.             errno = EWOULDBLOCK;
  580.             return EOF;
  581.         } else if((errno = (int)pwait(up)) != 0){
  582.             return EOF;
  583.         }
  584.     }
  585.     if(up->cb.p == NULLCHAR){
  586.         /* Blown away */
  587.         errno = EBADF;
  588.         return EOF;
  589.     }
  590.     i = up->rdysock;
  591.     up->rdysock = -1;
  592.  
  593.     up = itop(i);
  594.  
  595.     if(peername != NULLCHAR && peernamelen != 0){
  596.         *peernamelen = (int)min(up->peernamelen,*peernamelen);
  597.         memcpy(peername,up->peername,*peernamelen);
  598.     }
  599.     return i;
  600. }
  601.  
  602. /* Low-level receive routine. Passes mbuf back to user; more efficient than
  603.  * higher-level functions recv() and recvfrom(). Datagram sockets ignore
  604.  * the len parameter.
  605.  */
  606. int
  607. recv_mbuf(
  608. int s,                    /* Socket index */
  609. struct mbuf **bpp,        /* Place to stash receive buffer */
  610. int flags,                /* Unused; will control out-of-band data, etc */
  611. char *from,                /* Peer address (only for datagrams) */
  612. int *fromlen)            /* Length of peer address */
  613. {
  614.     struct usock *up;
  615.     int cnt = -1;
  616.     union cb cb;
  617.     struct socket fsocket;
  618. #ifdef    NETROM
  619.     struct nr3hdr n3hdr;
  620. #endif
  621.     union sp remote;
  622.     struct ip ip;
  623.     struct mbuf *bp;
  624.  
  625.     if((up = itop(s)) == NULLUSOCK){
  626.         return EOF;
  627.     }
  628.     if(up->ibuf != NULLBUF){
  629.         /* Return input buffer */
  630.         cnt = len_p(up->ibuf);
  631.         if(bpp != NULLBUFP)
  632.             *bpp = up->ibuf;
  633.         else
  634.             free_p(up->ibuf);
  635.         up->ibuf = NULLBUF;
  636.         return cnt;
  637.     }
  638.     switch(up->type){
  639.     case TYPE_LOCAL_STREAM:
  640.     case TYPE_LOCAL_DGRAM:
  641.         while(up->cb.local != NULLLOC && up->cb.local->q == NULLBUF
  642.           && up->cb.local->peer != NULLUSOCK) {
  643.             if(up->noblock){
  644.                 errno = EWOULDBLOCK;
  645.                 return EOF;
  646.             } else if((errno = (int)pwait(up)) != 0){
  647.                 return EOF;
  648.             }
  649.         }
  650.         if(up->cb.local == NULLLOC){
  651.             errno = EBADF;
  652.             return EOF;
  653.         }
  654.         if(up->cb.local->q == NULLBUF &&
  655.            up->cb.local->peer == NULLUSOCK){
  656.             errno = ENOTCONN;
  657.             return EOF;
  658.         }
  659.         /* For datagram sockets, this will return the
  660.          * first packet on the queue. For stream sockets,
  661.          * this will return everything.
  662.          */
  663.         bp = dequeue(&up->cb.local->q);
  664.         if(up->cb.local->q == NULLBUF && (up->cb.local->flags & LOC_SHUTDOWN))
  665.             close_s(s);
  666.         psignal(up,0);
  667.         cnt = len_p(bp);
  668.         break;
  669.     case TYPE_TCP:
  670.         while((cb.tcb = up->cb.tcb) != NULLTCB
  671.           && cb.tcb->r_upcall != trdiscard
  672.           && (cnt = recv_tcp(cb.tcb,&bp,0)) == -1){
  673.             if(up->noblock){
  674.                 errno = EWOULDBLOCK;
  675.                 return EOF;
  676.             } else if((errno = (int)pwait(up)) != 0){
  677.                 return EOF;
  678.             }
  679.         }
  680.         if(cb.tcb == NULLTCB){
  681.             /* Connection went away */
  682.             errno = ENOTCONN;
  683.             return EOF;
  684.         } else if(cb.tcb->r_upcall == trdiscard){
  685.             /* Receive shutdown has been done */
  686.             errno = ENOTCONN;    /* CHANGE */
  687.             return EOF;
  688.         }
  689.         break;
  690. #ifdef UDP
  691.     case TYPE_UDP:
  692.         while((cb.udp = up->cb.udp) != NULLUDP
  693.           && (cnt = recv_udp(cb.udp,&fsocket,&bp)) == -1){
  694.             if(up->noblock){
  695.                 errno = EWOULDBLOCK;
  696.                 return EOF;
  697.             } else if((errno = (int)pwait(up)) != 0){
  698.                 return EOF;
  699.             }
  700.         }
  701.         if(cb.udp == NULLUDP){
  702.             /* Connection went away */
  703.             errno = ENOTCONN;
  704.             return EOF;
  705.         }
  706.         if(from != NULLCHAR && fromlen != 0 && *fromlen >= SOCKSIZE){
  707.             remote.in = (struct sockaddr_in *)from;
  708.             remote.in->sin_family = AF_INET;
  709.             remote.in->sin_addr.s_addr = fsocket.address;
  710.             remote.in->sin_port = fsocket.port;
  711.             *fromlen = SOCKSIZE;
  712.         }
  713.         break;
  714. #endif
  715.     case TYPE_RAW:
  716.         while((cb.rip = up->cb.rip) != NULLRIP
  717.          && cb.rip->rcvq == NULLBUF){
  718.             if(up->noblock){
  719.                 errno = EWOULDBLOCK;
  720.                 return EOF;
  721.             } else if((errno = (int)pwait(up)) != 0){
  722.                 return EOF;
  723.             }
  724.         }
  725.         if(cb.rip == NULLRIP){
  726.             /* Connection went away */
  727.             errno = ENOTCONN;
  728.             return EOF;
  729.         }
  730.         bp = dequeue(&cb.rip->rcvq);
  731.         ntohip(&ip,&bp);
  732.  
  733.         cnt = len_p(bp);
  734.         if(from != NULLCHAR && fromlen != 0 && *fromlen >= SOCKSIZE){
  735.             remote.in = (struct sockaddr_in *)from;
  736.             remote.in->sin_family = AF_INET;
  737.             remote.in->sin_addr.s_addr = ip.source;
  738.             remote.in->sin_port = 0;
  739.             *fromlen = SOCKSIZE;
  740.         }
  741.         break;
  742. #ifdef    AX25
  743.     case TYPE_AX25I:
  744.         while((cb.ax25 = up->cb.ax25) != NULLAX25
  745.          && (bp = recv_ax25(cb.ax25,0)) == NULLBUF){
  746.             if(up->noblock){
  747.                 errno = EWOULDBLOCK;
  748.                 return EOF;
  749.             } else if((errno = (int)pwait(up)) != 0){
  750.                 return EOF;
  751.             }
  752.         }
  753.         if(cb.ax25 == NULLAX25){
  754.             /* Connection went away */
  755.             errno = ENOTCONN;
  756.             return EOF;
  757.         }
  758.         cnt = bp->cnt;
  759.         break;
  760.     case TYPE_AX25UI:
  761.         while(s == Axui_sock) {
  762.             if(up->noblock){
  763.                 errno = EWOULDBLOCK;
  764.                 return EOF;
  765.             }
  766.         }
  767.         if(s != Axui_sock){
  768.             errno = ENOTCONN;
  769.             return EOF;
  770.         }
  771.         bp = NULLBUF;
  772.  
  773.         if(from != NULLCHAR && fromlen != NULLINT
  774.            && *fromlen >= sizeof(struct sockaddr_ax)){
  775.             pullup(&bp,from,sizeof(struct sockaddr_ax));
  776.             *fromlen = sizeof(struct sockaddr_ax);
  777.         } else {
  778.             pullup(&bp,NULLCHAR,sizeof(struct sockaddr_ax));
  779.         }
  780.         cnt = len_p(bp);
  781.         break;
  782. #endif
  783. #ifdef NETROM
  784.     case TYPE_NETROML3:
  785.         while((cb.rnr = up->cb.rnr) != NULLRNR
  786.          && cb.rnr->rcvq == NULLBUF){
  787.             if(up->noblock){
  788.                 errno = EWOULDBLOCK;
  789.                 return EOF;
  790.             } else if((errno = (int)pwait(up)) != 0){
  791.                 return EOF;
  792.             }
  793.         }
  794.         if(cb.rnr == NULLRNR){
  795.             /* Connection went away */
  796.             errno = ENOTCONN;
  797.             return EOF;
  798.         }
  799.         bp = dequeue(&cb.rnr->rcvq);
  800.         ntohnr3(&n3hdr,&bp);
  801.         cnt = len_p(bp);
  802.         if(from != NULLCHAR && fromlen != NULLINT
  803.            && *fromlen >= sizeof(struct sockaddr_nr)){
  804.             remote.nr = (struct sockaddr_nr *)from;
  805.             remote.nr->nr_family = AF_NETROM;
  806.             /* The callsign of the local user is not part of
  807.                NET/ROM level 3, so that field is not used here */
  808.             memcpy(remote.nr->nr_addr.node,n3hdr.source,AXALEN);
  809.             *fromlen = sizeof(struct sockaddr_nr);
  810.         }
  811.         break;
  812.     case TYPE_NETROML4:
  813.         while((cb.nr4 = up->cb.nr4) != NULLNR4CB
  814.          && (bp = recv_nr4(cb.nr4,0)) == NULLBUF){
  815.             if(up->noblock){
  816.                 errno = EWOULDBLOCK;
  817.                 return EOF;
  818.             } else if((errno = (int)pwait(up)) != 0){
  819.                 return EOF;
  820.             }
  821.         }
  822.         if(cb.nr4 == NULLNR4CB){
  823.             /* Connection went away */
  824.             errno = ENOTCONN;
  825.             return EOF;
  826.         }
  827.         cnt = bp->cnt;
  828.         break;
  829. #endif
  830.     }
  831.     if(bpp != NULLBUFP)
  832.         *bpp = bp;
  833.     else
  834.         free_p(bp);
  835.     return cnt;
  836. }
  837.  
  838. /* Low level send routine; user supplies mbuf for transmission. More
  839.  * efficient than send() or sendto(), the higher level interfaces.
  840.  * The "to" and "tolen" parameters are ignored on connection-oriented
  841.  * sockets.
  842.  *
  843.  * In case of error, bp is freed so the caller doesn't have to worry about it.
  844.  */
  845. int
  846. send_mbuf(
  847. int s,                    /* Socket index */
  848. struct mbuf *bp,        /* Buffer to send */
  849. int flags,                /* not currently used */
  850. char *to,                /* Destination, only for datagrams */
  851. int tolen)                /* Length of destination */
  852. {
  853.     struct usock *up;
  854.     union cb cb;
  855.     union sp local,remote;
  856.     struct socket lsock,fsock;
  857.     int cnt;
  858.  
  859.     if((up = itop(s)) == NULLUSOCK) {
  860.         free_p(bp);
  861.         return EOF;
  862.     }
  863.     if(up->obuf != NULLBUF) {
  864.         /* If there's unflushed output, send it.
  865.          * Note the importance of clearing up->obuf
  866.          * before the recursive call!
  867.          */
  868.         struct mbuf *bp1;
  869.  
  870.         bp1 = up->obuf;
  871.         up->obuf = NULLBUF;
  872.         send_mbuf(s,bp1,flags,to,tolen);
  873.     }
  874.     if(up->name == NULLCHAR) {
  875.         /* Automatic local name assignment for datagram sockets */
  876.         switch(up->type){
  877.         case TYPE_LOCAL_STREAM:
  878.         case TYPE_LOCAL_DGRAM:
  879.             break;    /* no op */
  880. #ifdef UDP
  881.         case TYPE_UDP:
  882. #endif
  883.         case TYPE_RAW:
  884.             autobind(s,AF_INET);
  885.             break;
  886. #ifdef    AX25
  887.         case TYPE_AX25UI:
  888.             autobind(s,AF_AX25);
  889.             break;
  890. #endif
  891. #ifdef    NETROM
  892.         case TYPE_NETROML3:
  893.         case TYPE_NETROML4:
  894.             autobind(s,AF_NETROM);
  895.             break;
  896. #endif
  897.         default:
  898.             free_p(bp);
  899.             errno = ENOTCONN;
  900.             return EOF;
  901.         }
  902.     }
  903.     cnt = len_p(bp);
  904.     switch(up->type){
  905.     case TYPE_LOCAL_DGRAM:
  906.         if(up->cb.local->peer == NULLUSOCK){
  907.             free_p(bp);
  908.             errno = ENOTCONN;
  909.             return EOF;
  910.         }
  911.         enqueue(&up->cb.local->peer->cb.local->q,bp);
  912.         psignal(up->cb.local->peer,0);
  913.         /* If high water mark has been reached, block */
  914.         while(len_q(up->cb.local->q) >= up->cb.local->hiwat){
  915.             if(up->noblock){
  916.                 errno = EWOULDBLOCK;
  917.                 return EOF;
  918.             } else if((errno = (int)pwait(up->cb.local->peer)) != 0){
  919.                 return EOF;
  920.             }
  921.         }
  922.         if(up->cb.local->peer == NULLUSOCK){
  923.             errno = ENOTCONN;
  924.             return EOF;
  925.         }
  926.         break;
  927.     case TYPE_LOCAL_STREAM:
  928.         if(up->cb.local->peer == NULLUSOCK){
  929.             free_p(bp);
  930.             errno = ENOTCONN;
  931.             return EOF;
  932.         }
  933.         append(&up->cb.local->peer->cb.local->q,bp);
  934.         psignal(up->cb.local->peer,0);
  935.         /* If high water mark has been reached, block */
  936.         while(up->cb.local->peer != NULLUSOCK &&
  937.               len_p(up->cb.local->peer->cb.local->q) >=
  938.               up->cb.local->peer->cb.local->hiwat){
  939.             if(up->noblock){
  940.                 errno = EWOULDBLOCK;
  941.                 return EOF;
  942.             } else if((errno = (int)pwait(up->cb.local->peer)) != 0){
  943.                 return EOF;
  944.             }
  945.         }
  946.         if(up->cb.local->peer == NULLUSOCK){
  947.             errno = ENOTCONN;
  948.             return EOF;
  949.         }
  950.         break;
  951.     case TYPE_TCP:
  952.         if((cb.tcb = up->cb.tcb) == NULLTCB){
  953.             free_p(bp);
  954.             errno = ENOTCONN;
  955.             return EOF;
  956.         }
  957.         cnt = send_tcp(cb.tcb,bp);
  958.  
  959.         while((cb.tcb = up->cb.tcb) != NULLTCB &&
  960.          cb.tcb->sndcnt > cb.tcb->window){
  961.             /* Send queue is full */
  962.             if(up->noblock){
  963.                 errno = EWOULDBLOCK;
  964.                 return EOF;
  965.             } else if((errno = (int)pwait(up)) != 0){
  966.                 return EOF;
  967.             }
  968.         }
  969.          if(cb.tcb == NULLTCB){
  970.             errno = ENOTCONN;
  971.             return EOF;
  972.         }
  973.         break;
  974. #ifdef UDP
  975.     case TYPE_UDP:
  976.         local.in = (struct sockaddr_in *)up->name;
  977.         lsock.address = local.in->sin_addr.s_addr;
  978.         lsock.port = local.in->sin_port;
  979.         if(to != NULLCHAR)
  980.             remote.in = (struct sockaddr_in *)to;
  981.         else if(up->peername != NULLCHAR)
  982.             remote.in = (struct sockaddr_in *)up->peername;
  983.         else {
  984.             errno = ENOTCONN;
  985.             return EOF;
  986.         }
  987.         fsock.address = remote.in->sin_addr.s_addr;
  988.         fsock.port = remote.in->sin_port;
  989.         send_udp(&lsock,&fsock,0,0,bp,0,0,0);
  990.         break;
  991. #endif
  992.     case TYPE_RAW:
  993.         local.in = (struct sockaddr_in *)up->name;
  994.         if(to != NULLCHAR)
  995.             remote.in = (struct sockaddr_in *)to;
  996.         else if(up->peername != NULLCHAR)
  997.             remote.in = (struct sockaddr_in *)up->peername;
  998.         else {
  999.             errno = ENOTCONN;
  1000.             return EOF;
  1001.         }
  1002.         ip_send(local.in->sin_addr.s_addr,remote.in->sin_addr.s_addr,
  1003.             up->cb.rip->protocol,0,0,bp,0,0,0);
  1004.         break;
  1005. #ifdef    AX25
  1006.     case TYPE_AX25I:
  1007.         if((cb.ax25 = up->cb.ax25) == NULLAX25){
  1008.             free_p(bp);
  1009.             errno = ENOTCONN;
  1010.             return EOF;
  1011.         }
  1012.         send_ax25(cb.ax25,bp,STREAM);
  1013.  
  1014.         while((cb.ax25 = up->cb.ax25) != NULLAX25 &&
  1015.          len_p(cb.ax25->txq) > Axwindow){
  1016.             if(up->noblock){
  1017.                 errno = EWOULDBLOCK;
  1018.                 return EOF;
  1019.             } else if((errno = (int)pwait(up)) != 0){
  1020.                 errno = EINTR;
  1021.                 return EOF;
  1022.             }
  1023.         }
  1024.         if(cb.ax25 == NULLAX25){
  1025.             errno = EBADF;
  1026.             return EOF;
  1027.         }
  1028.         break;
  1029.     case TYPE_AX25UI:
  1030.         local.ax = (struct sockaddr_ax *)up->name;
  1031.         if(to != NULLCHAR)
  1032.             remote.ax = (struct sockaddr_ax *)to;
  1033.         else if(up->peername != NULLCHAR)
  1034.             remote.ax = (struct sockaddr_ax *)up->peername;
  1035.         else {
  1036.             errno = ENOTCONN;
  1037.             return EOF;
  1038.         }
  1039.         ax_output(if_lookup(remote.ax->iface),
  1040.               remote.ax->ax25_addr,
  1041.               local.ax->ax25_addr,PID_NO_L3,bp);
  1042.         break;
  1043. #endif
  1044. #ifdef NETROM
  1045.     case TYPE_NETROML3:
  1046.         if(len_p(bp) > Nr_iface->mtu) {
  1047.             free_p(bp);
  1048.             errno = EMSGSIZE;
  1049.             return EOF;
  1050.         }
  1051.         local.nr = (struct sockaddr_nr *)up->name;
  1052.         if(to != NULLCHAR)
  1053.             remote.nr = (struct sockaddr_nr *)to;
  1054.         else if(up->peername != NULLCHAR)
  1055.             remote.nr = (struct sockaddr_nr *)up->peername;
  1056.         else {
  1057.             errno = ENOTCONN;
  1058.             return EOF;
  1059.         }
  1060.         /* The NETROM username is always ignored in outgoing traffic */
  1061.         nr_sendraw(remote.nr->nr_addr.node,
  1062.          up->cb.rnr->protocol,up->cb.rnr->protocol,bp);
  1063.         break;
  1064.     case TYPE_NETROML4:
  1065.         if((cb.nr4 = up->cb.nr4) == NULLNR4CB) {
  1066.             free_p(bp);
  1067.             errno = ENOTCONN;
  1068.             return EOF;
  1069.         }
  1070.         if(len_p(bp) > Nr_iface->mtu){ /* reject big packets */
  1071.             free_p(bp);
  1072.             errno = EMSGSIZE;
  1073.             return EOF;
  1074.         }
  1075.         send_nr4(cb.nr4,bp);
  1076.  
  1077.         while((cb.nr4 = up->cb.nr4) != NULLNR4CB &&
  1078.          cb.nr4->nbuffered >= cb.nr4->window){
  1079.             if(up->noblock){
  1080.                 errno = EWOULDBLOCK;
  1081.                 return EOF;
  1082.             } else if((errno = (int)pwait(up)) != 0){
  1083.                 errno = EINTR;
  1084.                 return EOF;
  1085.             }
  1086.         }
  1087.         if(cb.nr4 == NULLNR4CB){
  1088.             errno = EBADF;
  1089.             return EOF;
  1090.         }
  1091.         break;
  1092. #endif
  1093.     }
  1094.     return cnt;
  1095. }
  1096.  
  1097. /* Return local name passed in an earlier bind() call */
  1098. int
  1099. getsockname(
  1100. int s,                    /* Socket index */
  1101. char *name,                /* Place to stash name */
  1102. int *namelen)            /* Length of same */
  1103. {
  1104.     struct usock *up;
  1105.  
  1106.     if((up = itop(s)) == NULLUSOCK){
  1107.         return EOF;
  1108.     }
  1109.     if(name == NULLCHAR || namelen == 0){
  1110.         errno = EFAULT;
  1111.         return EOF;
  1112.     }
  1113.     if(up->name == NULLCHAR){
  1114.         /* Not bound yet */
  1115.         *namelen = 0;
  1116.         return 0;
  1117.     }
  1118.     if(up->name != NULLCHAR){
  1119.         *namelen = (int)min(*namelen,up->namelen);
  1120.         memcpy(name,up->name,*namelen);
  1121.     }
  1122.     return 0;
  1123. }
  1124.  
  1125. /* Get remote name, returning result of earlier connect() call. */
  1126. int
  1127. getpeername(
  1128. int s,                    /* Socket index */
  1129. char *peername,            /* Place to stash name */
  1130. int *peernamelen)        /* Length of same */
  1131. {
  1132.     struct usock *up;
  1133.  
  1134.     if((up = itop(s)) == NULLUSOCK){
  1135.         return EOF;
  1136.     }
  1137.     if(up->peername == NULLCHAR){
  1138.         errno = ENOTCONN;
  1139.         return EOF;
  1140.     }
  1141.     if(peername == NULLCHAR || peernamelen == 0){
  1142.         errno = EFAULT;
  1143.         return EOF;
  1144.     }
  1145.     *peernamelen = (int)min(*peernamelen,up->peernamelen);
  1146.     memcpy(peername,up->peername,*peernamelen);
  1147.     return 0;
  1148. }
  1149.  
  1150. /* Return length of protocol queue, either send or receive. */
  1151. int
  1152. socklen(
  1153. int s,                    /* Socket index */
  1154. int rtx)                /* 0 = receive queue, 1 = transmit queue */
  1155. {
  1156.     struct usock *up;
  1157.     int len = -1;
  1158.  
  1159.     if((up = itop(s)) == NULLUSOCK){
  1160.         return EOF;
  1161.     }
  1162.     if(up->cb.p == NULLCHAR){
  1163.         errno = ENOTCONN;
  1164.         return EOF;
  1165.     }
  1166.     if(rtx < 0 || rtx > 1) {
  1167.         errno = EINVAL;
  1168.         return EOF;
  1169.     }
  1170.     switch(up->type){
  1171.     case TYPE_LOCAL_DGRAM:
  1172.         switch(rtx){
  1173.         case 0:
  1174.             len = len_q(up->cb.local->q);
  1175.             break;
  1176.         case 1:
  1177.             if(up->cb.local->peer != NULLUSOCK) {
  1178.                 len = len_q(up->cb.local->peer->cb.local->q);
  1179.             }
  1180.             break;
  1181.         }
  1182.         break;
  1183.     case TYPE_LOCAL_STREAM:
  1184.         switch(rtx){
  1185.         case 0:
  1186.             len = len_p(up->cb.local->q) + len_p(up->ibuf);
  1187.             break;
  1188.         case 1:
  1189.             if(up->cb.local->peer != NULLUSOCK) {
  1190.                 len = len_p(up->cb.local->peer->cb.local->q) + len_p(up->obuf);
  1191.             }
  1192.             break;
  1193.         }
  1194.         break;
  1195.     case TYPE_TCP:
  1196.         switch(rtx){
  1197.         case 0:
  1198.             len = up->cb.tcb->rcvcnt + len_p(up->ibuf);
  1199.             break;
  1200.         case 1:
  1201.             len = up->cb.tcb->sndcnt + len_p(up->obuf);
  1202.             break;
  1203.         }
  1204.         break;
  1205. #ifdef UDP
  1206.     case TYPE_UDP:
  1207.         switch(rtx){
  1208.         case 0:
  1209.             len = up->cb.udp->rcvcnt;
  1210.             break;
  1211.         case 1:
  1212.             len = 0;
  1213.             break;
  1214.         }
  1215.         break;
  1216. #endif
  1217. #ifdef    AX25
  1218.     case TYPE_AX25I:
  1219.         switch(rtx){
  1220.         case 0:
  1221.             len = len_p(up->cb.ax25->rxq) + len_p(up->ibuf);
  1222.             break;
  1223.         case 1:    /* Number of bytes, not packets. DB3FL.910129 */
  1224.             len = len_p(up->cb.ax25->txq);
  1225.             if(up->obuf != NULLBUF)
  1226.                 len++;
  1227.         }
  1228.         break;
  1229.     case TYPE_AX25UI:
  1230.         switch(rtx){
  1231.         case 0:
  1232.         case 1:
  1233.             len = 0;
  1234.             break;
  1235.         }
  1236.         break;
  1237. #endif
  1238. #ifdef NETROM
  1239.     case TYPE_NETROML3:
  1240.         switch(rtx){
  1241.         case 0:
  1242.             len = len_q(up->cb.rnr->rcvq);
  1243.             break;
  1244.         case 1:
  1245.             len = 0;
  1246.             break;
  1247.         }
  1248.         break;
  1249.     case TYPE_NETROML4:
  1250.         switch(rtx){
  1251.         case 0:
  1252.             len = len_p(up->cb.nr4->rxq) + len_p(up->obuf);
  1253.             break;
  1254.         case 1:    /* Number of bytes, not packets. DB3FL.900129 */
  1255.             len = len_p(up->cb.nr4->txq);
  1256.             if(up->obuf != NULLBUF)
  1257.                 len++;
  1258.             break;
  1259.         }
  1260.         break;
  1261. #endif
  1262.     case TYPE_RAW:
  1263.         switch(rtx){
  1264.         case 0:
  1265.             len = len_q(up->cb.rip->rcvq);
  1266.             break;
  1267.         case 1:
  1268.             len = 0;
  1269.             break;
  1270.         }
  1271.         break;
  1272.     }
  1273.     return len;
  1274. }
  1275.  
  1276. /* Force retransmission. Valid only for connection-oriented sockets. */
  1277. int
  1278. sockkick(int s)
  1279. {
  1280.     struct usock *up;
  1281.  
  1282.     if((up = itop(s)) == NULLUSOCK){
  1283.         return EOF;
  1284.     }
  1285.     if(up->type == TYPE_LOCAL_STREAM || up->type == TYPE_LOCAL_DGRAM){
  1286.         errno = EINVAL;
  1287.         return EOF;
  1288.     }
  1289.     if(up->cb.p == NULLCHAR){
  1290.         errno = ENOTCONN;
  1291.         return EOF;
  1292.     }
  1293.     switch(up->type){
  1294.     case TYPE_TCP:
  1295.         kick_tcp(up->cb.tcb);
  1296.         break;
  1297. #ifdef    AX25
  1298.     case TYPE_AX25I:
  1299.         kick_ax25(up->cb.ax25);
  1300.         break;
  1301. #endif
  1302. #ifdef NETROM
  1303.     case TYPE_NETROML4:
  1304.         kick_nr4(up->cb.nr4);
  1305.         break;
  1306. #endif
  1307.     default:
  1308.         /* Datagram sockets can't be kicked */
  1309.         errno = EOPNOTSUPP;
  1310.         return EOF;
  1311.     }
  1312.     return 0;
  1313. }
  1314.  
  1315. /* Change owner of socket, return previous owner */
  1316. struct proc *
  1317. sockowner(int s,struct proc *newowner)
  1318. {
  1319.     struct usock *up;
  1320.     struct proc *pp;
  1321.  
  1322.     if((up = itop(s)) == NULLUSOCK){
  1323.         return NULLPROC;
  1324.     }
  1325.     pp = up->owner;
  1326.  
  1327.     if(newowner != NULLPROC)
  1328.         up->owner = newowner;
  1329.  
  1330.     return pp;
  1331. }
  1332.  
  1333. /* Close down a socket three ways. Type 0 means "no more receives"; this
  1334.  * replaces the incoming data upcall with a routine that discards further
  1335.  * data. Type 1 means "no more sends", and obviously corresponds to sending
  1336.  * a TCP FIN. Type 2 means "no more receives or sends". This I interpret
  1337.  * as "abort the connection".
  1338.  */
  1339. int
  1340. shutdown(int s,int how)
  1341. {
  1342.     struct usock *up;
  1343.  
  1344.     if((up = itop(s)) == NULLUSOCK){
  1345.         return EOF;
  1346.     }
  1347.     if(up->cb.p == NULLCHAR){
  1348.         errno = ENOTCONN;
  1349.         return EOF;
  1350.     }
  1351.     switch(up->type){
  1352.     case TYPE_LOCAL_DGRAM:
  1353.     case TYPE_LOCAL_STREAM:
  1354.         if(up->cb.local->q == NULLBUF)
  1355.             close_s(s);
  1356.         else
  1357.             up->cb.local->flags = LOC_SHUTDOWN;
  1358.         break;
  1359.     case TYPE_TCP:
  1360.         switch(how){
  1361.         case 0:    /* No more receives -- replace upcall */
  1362.             up->cb.tcb->r_upcall = trdiscard;
  1363.             break;
  1364.         case 1:    /* Send EOF */
  1365.             close_tcp(up->cb.tcb);
  1366.             break;
  1367.         case 2:    /* Blow away TCB */
  1368.             reset_tcp(up->cb.tcb);
  1369.             up->cb.tcb = NULLTCB;
  1370.             break;
  1371.         }
  1372.         break;
  1373. #ifdef    AX25
  1374.     case TYPE_AX25UI:
  1375.         close_s(s);
  1376.         break;
  1377.     case TYPE_AX25I:
  1378.         switch(how){
  1379.         case 0:
  1380.         case 1:    /* Attempt regular disconnect */
  1381.             disc_ax25(up->cb.ax25);
  1382.             break;
  1383.         case 2: /* Blow it away */
  1384.             reset_ax25(up->cb.ax25);
  1385.             up->cb.ax25 = NULLAX25;
  1386.             break;
  1387.         }
  1388.         break;
  1389. #endif
  1390. #ifdef    NETROM
  1391.     case TYPE_NETROML3:
  1392.         close_s(s);
  1393.         break;
  1394.     case TYPE_NETROML4:
  1395.         switch(how){
  1396.         case 0:
  1397.         case 1:    /* Attempt regular disconnect */
  1398.             disc_nr4(up->cb.nr4);
  1399.             break;
  1400.         case 2: /* Blow it away */
  1401.             reset_nr4(up->cb.nr4);
  1402.             up->cb.nr4 = NULLNR4CB;
  1403.             break;
  1404.         }
  1405.         break;
  1406. #endif
  1407.     case TYPE_RAW:
  1408. #ifdef UDP
  1409.     case TYPE_UDP:
  1410. #endif
  1411.         close_s(s);
  1412.         break;
  1413.     default:
  1414.         errno = EOPNOTSUPP;
  1415.         return EOF;
  1416.     }
  1417.     psignal(up,0);
  1418.     return 0;
  1419. }
  1420.  
  1421. /* Close a socket, freeing it for reuse. Try to do a graceful close on a
  1422.  * TCP socket, if possible
  1423.  */
  1424. int
  1425. close_s(int s)
  1426. {
  1427.     struct usock *up;
  1428.  
  1429.     if((up = itop(s)) == NULLUSOCK){
  1430.         return EOF;
  1431.     }
  1432.     if(--up->refcnt > 0) {
  1433.         /* Others are still using it */
  1434.         return 0;
  1435.     }
  1436.     usflush(s);
  1437.  
  1438.     if(up->ibuf != NULLBUF) {
  1439.         free_p(up->ibuf);
  1440.         up->ibuf = NULLBUF;
  1441.     }
  1442.     switch(up->type) {
  1443.     case TYPE_LOCAL_STREAM:
  1444.     case TYPE_LOCAL_DGRAM:
  1445.         if(up->cb.local->peer != NULLUSOCK) {
  1446.             up->cb.local->peer->cb.local->peer = NULLUSOCK;
  1447.             psignal(up->cb.local->peer,0);
  1448.         }
  1449.         free_q(&up->cb.local->q);
  1450.         xfree(up->cb.local);
  1451.         break;
  1452.     case TYPE_TCP:
  1453.         if(up->cb.tcb != NULLTCB) {        /* In case it's been reset */
  1454.             up->cb.tcb->r_upcall = trdiscard;
  1455.             /* Tell the TCP_CLOSED upcall there's no more socket */
  1456.             up->cb.tcb->user = -1;
  1457.             close_tcp(up->cb.tcb);
  1458.         }
  1459.         break;
  1460. #ifdef UDP
  1461.     case TYPE_UDP:
  1462.         if(up->cb.udp != NULLUDP) {
  1463.             del_udp(up->cb.udp);
  1464.         }
  1465.         break;
  1466. #endif
  1467. #ifdef    AX25
  1468.     case TYPE_AX25I:
  1469.         if(up->cb.ax25 != NULLAX25) {
  1470.             /* Tell the TCP_CLOSED upcall there's no more socket */
  1471.             up->cb.ax25->user = -1;
  1472.             disc_ax25(up->cb.ax25);
  1473.         }
  1474.         break;
  1475.     case TYPE_AX25UI:
  1476.         Axui_sock = -1;
  1477.         break;
  1478. #endif
  1479. #ifdef    NETROM
  1480.     case TYPE_NETROML3:
  1481.         del_rnr(up->cb.rnr);
  1482.         break;
  1483.     case TYPE_NETROML4:
  1484.         if(up->cb.nr4 != NULLNR4CB) {
  1485.             /* Tell the TCP_CLOSED upcall there's no more socket */
  1486.             up->cb.nr4->user = -1;
  1487.             disc_nr4(up->cb.nr4);
  1488.         }
  1489.         break;
  1490. #endif
  1491.     case TYPE_RAW:
  1492.         del_ip(up->cb.rip);
  1493.         break;
  1494.     default:
  1495.         errno = EOPNOTSUPP;
  1496.         return EOF;
  1497.     }
  1498. #ifdef    LZW
  1499.     if(up->zout != NULLLZW || up->zin != NULLLZW)
  1500.         lzwfree(up);
  1501. #endif
  1502.  
  1503.     if(up->name != NULLCHAR) {
  1504.         xfree(up->name);
  1505.     }
  1506.     if(up->peername != NULLCHAR) {
  1507.         xfree(up->peername);
  1508.     }
  1509.     up->name = up->peername = NULLCHAR;
  1510.     up->namelen = up->peernamelen = 0;
  1511.  
  1512.     up->cb.p = NULLCHAR;
  1513.     up->type = NOTUSED;
  1514.  
  1515.     /* Wake up anybody doing an accept() or recv() */
  1516.     psignal(up,0);
  1517.     return 0;
  1518. }
  1519.  
  1520. /* Increment reference count for specified socket */
  1521. int
  1522. usesock(int s)
  1523. {
  1524.     struct usock *up;
  1525.  
  1526.     if((up = itop(s)) == NULLUSOCK){
  1527.         return EOF;
  1528.     }
  1529.     up->refcnt++;
  1530.     return 0;
  1531. }
  1532.  
  1533. /* Blow away all sockets belonging to a certain process. Used by killproc(). */
  1534. void
  1535. freesock(struct proc *pp)
  1536. {
  1537.     struct usock *up;
  1538.     int i;
  1539.  
  1540.     for(i = SOCKBASE; i < (Nusock + SOCKBASE); i++)
  1541.         if((up = itop(i)) != NULLUSOCK)
  1542.             if(up->type != NOTUSED && up->owner == pp)
  1543.                 shutdown(i,2);
  1544. }
  1545.  
  1546. /* Start of internal subroutines */
  1547.  
  1548. /* Raw IP receive upcall routine */
  1549. static void
  1550. rip_recv(struct raw_ip *rp)
  1551. {
  1552.     psignal(itop(rp->user),1);
  1553.     pwait(NULL);
  1554. }
  1555.  
  1556. #ifdef UDP
  1557. /* UDP receive upcall routine */
  1558. static void
  1559. s_urcall(struct iface *iface,struct udp_cb *udp,int cnt)
  1560. {
  1561.     psignal(itop(udp->user),1);
  1562.     pwait(NULL);
  1563. }
  1564. #endif
  1565.  
  1566. /* TCP receive upcall routine */
  1567. static void
  1568. s_trcall(struct tcb *tcb,int cnt)
  1569. {
  1570.     /* Wake up anybody waiting for data, and let them run */
  1571.     psignal(itop(tcb->user),1);
  1572.     pwait(NULL);
  1573. }
  1574.  
  1575. /* TCP transmit upcall routine */
  1576. static void
  1577. s_ttcall(struct tcb *tcb,int cnt)
  1578. {
  1579.     /* Wake up anybody waiting to send data, and let them run */
  1580.     psignal(itop(tcb->user),1);
  1581.     pwait(NULL);
  1582. }
  1583.  
  1584. /* TCP state change upcall routine */
  1585. static void
  1586. s_tscall(struct tcb *tcb,int old,int new)
  1587. {
  1588.     int s = tcb->user, ns;
  1589.     union sp sp;
  1590.     struct usock *nup, *oup, *up = itop(s);
  1591.  
  1592.     oup = up;
  1593.  
  1594.     switch(new){
  1595.     case TCP_CLOSED:
  1596.         /* Clean up. If the user has already closed the socket,
  1597.          * then up will be null (s was set to -1 by the close routine).
  1598.          * If not, then this is an abnormal close (e.g., a reset)
  1599.          * and clearing out the pointer in the socket structure will
  1600.          * prevent any further operations on what will be a freed
  1601.          * control block. Also wake up anybody waiting on events
  1602.          * related to this tcb so they will notice it disappearing.
  1603.          */
  1604.         if(up != NULLUSOCK){
  1605.             up->cb.tcb = NULLTCB;
  1606.             up->errcodes[0] = tcb->reason;
  1607.             up->errcodes[1] = tcb->type;
  1608.             up->errcodes[2] = tcb->code;
  1609.         }
  1610.         del_tcp(tcb);
  1611.         break;
  1612.     case TCP_SYN_RECEIVED:
  1613.         /* Handle an incoming connection. If this is a server TCB,
  1614.          * then we're being handed a "clone" TCB and we need to
  1615.          * create a new socket structure for it. In either case,
  1616.          * find out who we're talking to and wake up the guy waiting
  1617.          * for the connection.
  1618.          */
  1619.         if(tcb->flags.clone){
  1620.             /* Clone the socket */
  1621.             ns = socket(AF_INET,SOCK_STREAM,0);
  1622.             nup = itop(ns);
  1623.             ASSIGN(*nup,*up);
  1624.             tcb->user = ns;
  1625.             nup->cb.tcb = tcb;
  1626.             /* Allocate new memory for the name areas */
  1627.             nup->name = mxallocw(SOCKSIZE);
  1628.             nup->peername = mxallocw(SOCKSIZE);
  1629.             /* Store the new socket # in the old one */
  1630.             up->rdysock = ns;
  1631.             up = nup;
  1632.             s = ns;
  1633.         } else {
  1634.             /* Allocate space for the peer's name */
  1635.             up->peername = mxallocw(SOCKSIZE);
  1636.             /* Store the old socket # in the old socket */
  1637.             up->rdysock = s;
  1638.         }
  1639.         /* Load the addresses. Memory for the name has already
  1640.          * been allocated, either above or in the original bind.
  1641.          */
  1642.         sp.p = up->name;
  1643.         sp.in->sin_family = AF_INET;
  1644.         sp.in->sin_addr.s_addr = up->cb.tcb->conn.local.address;
  1645.         sp.in->sin_port = up->cb.tcb->conn.local.port;
  1646.         up->namelen = SOCKSIZE;
  1647.  
  1648.         sp.p = up->peername;
  1649.         sp.in->sin_family = AF_INET;
  1650.         sp.in->sin_addr.s_addr = up->cb.tcb->conn.remote.address;
  1651.         sp.in->sin_port = up->cb.tcb->conn.remote.port;
  1652.         up->peernamelen = SOCKSIZE;
  1653.  
  1654.         /* Wake up the guy accepting it, and let him run */
  1655.         psignal(oup,1);
  1656.         pwait(NULL);
  1657.         break;
  1658.     default:    /* Ignore all other state transitions */
  1659.         break;
  1660.     }
  1661.     psignal(up,0);    /* In case anybody's waiting */
  1662. }
  1663.  
  1664. /* Discard data received on a TCP connection. Used after a receive shutdown or
  1665.  * close_s until the TCB disappears.
  1666.  */
  1667. static void
  1668. trdiscard(struct tcb *tcb,int cnt)
  1669. {
  1670.     struct mbuf *bp;
  1671.  
  1672.     recv_tcp(tcb,&bp,cnt);
  1673.     free_p(bp);
  1674. }
  1675.  
  1676. /*
  1677. #ifdef    AX25        DB3FL
  1678. */
  1679. /* AX.25 receive upcall */
  1680. void
  1681. s_arcall(struct ax25_cb *axp,int cnt)
  1682. {
  1683.     int ns;
  1684.     union sp sp;
  1685.     struct usock *nup, *oup, *up = itop(axp->user);
  1686.  
  1687.     /* When AX.25 data arrives for the first time the AX.25 listener
  1688.        is notified, if active. If the AX.25 listener is a server its
  1689.        socket is duplicated in the same manner as in s_tscall().
  1690.      */
  1691.     if (Axi_sock != -1 && axp->user == -1) {
  1692.         oup = up = itop(Axi_sock);
  1693.         /* From now on, use the same upcalls as the listener */
  1694.         axp->t_upcall = up->cb.ax25->t_upcall;
  1695.         axp->r_upcall = up->cb.ax25->r_upcall;
  1696.         axp->s_upcall = up->cb.ax25->s_upcall;
  1697.         if (up->cb.ax25->clone) {
  1698.             /* Clone the socket */
  1699.             ns = socket(AF_AX25,SOCK_STREAM,0);
  1700.             nup = itop(ns);
  1701.             ASSIGN(*nup,*up);
  1702.             axp->user = ns;
  1703.             nup->cb.ax25 = axp;
  1704.             /* Allocate new memory for the name areas */
  1705.             nup->name = mxallocw(sizeof(struct sockaddr_ax));
  1706.             nup->peername = mxallocw(sizeof(struct sockaddr_ax));
  1707.             /* Store the new socket # in the old one */
  1708.             up->rdysock = ns;
  1709.             up = nup;
  1710.         } else {
  1711.             axp->user = Axi_sock;
  1712.             del_ax25(up->cb.ax25);
  1713.             up->cb.ax25 = axp;
  1714.             /* Allocate space for the peer's name */
  1715.             up->peername = mxallocw(sizeof(struct sockaddr_ax));
  1716.             /* Store the old socket # in the old socket */
  1717.             up->rdysock = Axi_sock;
  1718.         }
  1719.         /* Load the addresses. Memory for the name has already
  1720.          * been allocated, either above or in the original bind.
  1721.          */
  1722.         sp.p = up->name;
  1723.         sp.ax->sax_family = AF_AX25;
  1724.         memcpy(sp.ax->ax25_addr,axp->path + AXALEN,AXALEN);
  1725.         memcpy(sp.ax->iface,axp->iface->name,ILEN);
  1726.         up->namelen = sizeof(struct sockaddr_ax);
  1727.  
  1728.         sp.p = up->peername;
  1729.         sp.ax->sax_family = AF_AX25;
  1730.         memcpy(sp.ax->ax25_addr,axp->path,AXALEN);
  1731.         memcpy(sp.ax->iface,axp->iface->name,ILEN);
  1732.         up->peernamelen = sizeof(struct sockaddr_ax);
  1733.         /* Wake up the guy accepting it, and let him run */
  1734.         psignal(oup,1);
  1735.         pwait(NULL);
  1736.         return;
  1737.     }
  1738.     /* Wake up anyone waiting, and let them run */
  1739.     psignal(up,1);
  1740.     pwait(NULL);
  1741. }
  1742.  
  1743. /* AX.25 transmit upcall */
  1744. void
  1745. s_atcall(struct ax25_cb *axp,int cnt)
  1746. {
  1747.     /* Wake up anyone waiting, and let them run */
  1748.     psignal(itop(axp->user),1);
  1749.     pwait(NULL);
  1750. }
  1751.  
  1752. /* AX25 state change upcall routine */
  1753. void
  1754. s_ascall(struct ax25_cb *axp,int old,int new)
  1755. {
  1756.     struct usock *up = itop(axp->user);
  1757.  
  1758.     switch(new){
  1759.     case DISCONNECTED:
  1760.         /* Clean up. If the user has already closed the socket,
  1761.          * then up will be null (s was set to -1 by the close routine).
  1762.          * If not, then this is an abnormal close (e.g., a reset)
  1763.          * and clearing out the pointer in the socket structure will
  1764.          * prevent any further operations on what will be a freed
  1765.          * control block. Also wake up anybody waiting on events
  1766.          * related to this block so they will notice it disappearing.
  1767.          */
  1768.         if(up != NULLUSOCK){
  1769.             up->errcodes[0] = axp->reason;
  1770.             up->cb.ax25 = NULLAX25;
  1771.         }
  1772.         del_ax25(axp);
  1773.     default:    /* Other transitions are ignored */
  1774.         break;
  1775.     }
  1776.     psignal(up,0);    /* In case anybody's waiting */
  1777. }
  1778.  
  1779. /*
  1780. #endif
  1781. */
  1782. #ifdef NETROM
  1783. /* NET/ROM receive upcall routine */
  1784. void
  1785. s_nrcall(struct nr4cb *cb,int cnt)
  1786. {
  1787.     /* Wake up anybody waiting for data, and let them run */
  1788.     psignal(itop(cb->user),1);
  1789.     pwait(NULL);
  1790. }
  1791.  
  1792. /* NET/ROM transmit upcall routine */
  1793. void
  1794. s_ntcall(struct nr4cb *cb,int cnt)
  1795. {
  1796.     /* Wake up anybody waiting to send data, and let them run */
  1797.     psignal(itop(cb->user),1);
  1798.     pwait(NULL);
  1799. }
  1800.  
  1801. /* NET/ROM state change upcall routine */
  1802. void
  1803. s_nscall(struct nr4cb *cb,int old,int new)
  1804. {
  1805.     int ns, s = cb->user;
  1806.     struct usock *oup, *nup, *up = itop(s);
  1807.     union sp sp;
  1808.  
  1809.     oup = up;
  1810.  
  1811.      if(new == NR4STDISC && up != NULLUSOCK){
  1812.         /* Clean up. If the user has already closed the socket,
  1813.          * then up will be null (s was set to -1 by the close routine).
  1814.          * If not, then this is an abnormal close (e.g., a reset)
  1815.          * and clearing out the pointer in the socket structure will
  1816.          * prevent any further operations on what will be a freed
  1817.          * control block. Also wake up anybody waiting on events
  1818.          * related to this cb so they will notice it disappearing.
  1819.          */
  1820.          up->cb.nr4 = NULLNR4CB;
  1821.          up->errcodes[0] = cb->dreason;
  1822.      }
  1823.      if(new == NR4STCON && old == NR4STDISC){
  1824.         /* Handle an incoming connection. If this is a server cb,
  1825.          * then we're being handed a "clone" cb and we need to
  1826.          * create a new socket structure for it. In either case,
  1827.          * find out who we're talking to and wake up the guy waiting
  1828.          * for the connection.
  1829.          */
  1830.         if(cb->clone){
  1831.             /* Clone the socket */
  1832.             ns = socket(AF_NETROM,SOCK_SEQPACKET,0);
  1833.             nup = itop(ns);
  1834.             ASSIGN(*nup,*up);
  1835.             cb->user = ns;
  1836.             nup->cb.nr4 = cb;
  1837.             cb->clone = 0; /* to avoid getting here again */
  1838.             /* Allocate new memory for the name areas */
  1839.             nup->name = mxallocw(sizeof(struct sockaddr_nr));
  1840.             nup->peername = mxallocw(sizeof(struct sockaddr_nr));
  1841.             /* Store the new socket # in the old one */
  1842.             up->rdysock = ns;
  1843.             up = nup;
  1844.             s = ns;
  1845.         } else {
  1846.             /* Allocate space for the peer's name */
  1847.             up->peername = mxallocw(sizeof(struct sockaddr_nr));
  1848.             /* Store the old socket # in the old socket */
  1849.             up->rdysock = s;
  1850.         }
  1851.         /* Load the addresses. Memory for the name has already
  1852.          * been allocated, either above or in the original bind.
  1853.          */
  1854.         sp.p = up->name;
  1855.         sp.nr->nr_family = AF_NETROM;
  1856.         ASSIGN(sp.nr->nr_addr,up->cb.nr4->local);
  1857.         up->namelen = sizeof(struct sockaddr_nr);
  1858.  
  1859.         sp.p = up->peername;
  1860.         sp.nr->nr_family = AF_NETROM;
  1861.         ASSIGN(sp.nr->nr_addr,up->cb.nr4->remote);
  1862.         up->peernamelen = sizeof(struct sockaddr_nr);
  1863.  
  1864.         /* Wake up the guy accepting it, and let him run */
  1865.         psignal(oup,1);
  1866.         pwait(NULL);
  1867.     }
  1868.      /* Ignore all other state transitions */    
  1869.     psignal(up,0);    /* In case anybody's waiting */
  1870. }
  1871. #endif
  1872.  
  1873. /* Verify address family and length according to the socket type */
  1874. static int near
  1875. checkaddr(int type,char *name,int namelen)
  1876. {
  1877.     struct sockaddr *sp = (struct sockaddr *)name;
  1878.  
  1879.     /* Verify length and address family according to protocol */
  1880.     switch(type){
  1881.     case TYPE_TCP:
  1882. #ifdef UDP
  1883.     case TYPE_UDP:
  1884. #endif
  1885.         if(sp->sa_family != AF_INET
  1886.           || namelen != sizeof(struct sockaddr_in))
  1887.             return EOF;
  1888.         break;
  1889. #ifdef    AX25
  1890.     case TYPE_AX25I:
  1891.     case TYPE_AX25UI:
  1892.         if(sp->sa_family != AF_AX25
  1893.           || namelen != sizeof(struct sockaddr_ax))
  1894.             return EOF;
  1895.         break;
  1896. #endif
  1897. #ifdef    NETROM
  1898.     case TYPE_NETROML3:
  1899.     case TYPE_NETROML4:
  1900.         if(sp->sa_family != AF_NETROM
  1901.           || namelen != sizeof(struct sockaddr_nr))
  1902.             return EOF;
  1903.         break;
  1904. #endif
  1905.     }
  1906.     return 0;
  1907. }
  1908.  
  1909. /* Issue an automatic bind of a local address */
  1910. static void near
  1911. autobind(int s,int af)
  1912. {
  1913.     char buf[MAXSOCKSIZE];
  1914.     union sp sp;
  1915.  
  1916.     memset(buf,0,sizeof(buf));
  1917.  
  1918.     sp.p = buf;
  1919.  
  1920.     switch(af){
  1921.     case AF_INET:
  1922.         sp.in->sin_family = AF_INET;
  1923.         sp.in->sin_addr.s_addr = INADDR_ANY;
  1924.         sp.in->sin_port = Lport++;
  1925.         bind(s,sp.p,sizeof(struct sockaddr_in));
  1926.         break;
  1927. #ifdef    AX25
  1928.     case AF_AX25:
  1929.         sp.ax->sax_family = AF_AX25;
  1930.         memset(sp.ax->ax25_addr,'\0',AXALEN);
  1931.         memset(sp.ax->iface,'\0',ILEN);
  1932.         bind(s,sp.p,sizeof(struct sockaddr_ax));
  1933.         break;
  1934. #endif
  1935. #ifdef    NETROM
  1936.     case AF_NETROM:
  1937.         sp.nr->nr_family = AF_NETROM;
  1938.         memcpy(sp.nr->nr_addr.user,Mycall,AXALEN);
  1939.         memcpy(sp.nr->nr_addr.node,Mycall,AXALEN);
  1940.         bind(s,sp.p,sizeof(struct sockaddr_nr));
  1941.         break;
  1942. #endif
  1943.     }
  1944. }
  1945.  
  1946. /* Convert a socket index to an internal user socket structure pointer */
  1947. struct usock *
  1948. itop(int s)                    /* Socket index */
  1949. {
  1950.     int sidx = s - SOCKBASE;
  1951.     struct usock *up = &Usock[sidx];
  1952.  
  1953.     if(up->type == NOTUSED || sidx < 0 || sidx >= Nusock) {
  1954.         errno = EBADF;
  1955.         return NULLUSOCK;
  1956.     }
  1957.     return up;
  1958. }
  1959.  
  1960.